package com.ad2campaign.engine.rest;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.web.client.RestOperations;

import com.ad2campaign.engine.db.model.Node;
/* @author Shubhanshu Shukla
 * This class is safe. 
 * */
public class RestfulActionExecutor implements ActionExecutor
{
	 public static String URLTemplate="%s://%s:%d/";
 	 private RestOperations restTemplate;
 	 private static final Logger LOGGER = Logger.getLogger(RestfulActionExecutor.class);
	 private ThreadLocal<StringBuilder> threadLocalStringBuilder = new ThreadLocal<StringBuilder>(){protected StringBuilder initialValue() {return new StringBuilder();}};
 	 

	/*
		 * To check that node is alive or not, this class invokes ping rest service of engine.
		 * @param node 
		 * @param action enum
		 * @param requestParameters ,will pass to rest template 
		 * @param urlVariables ,will pass to rest template
		 * */
 	public RestActionResponse execute(Node node,Action action,List<RequestParameter> requestParameters ,Map<String, ?> urlVariables )
	{	
 		String url ="";
		
 		if (requestParameters!=null)
 		{
 			url = String.format(URLTemplate,node.getProtocol(),node.getHost(),node.getPort())+action.toString() + "?"+requestParamListTostring(requestParameters);
 		}
 		else
 		{
 			url = String.format(URLTemplate,node.getProtocol(),node.getHost(),node.getPort())+action.toString() ;
 		}
	 	RestActionResponse response =null;
	 	try 
	 	{
	 		LOGGER.info(String.format( "loadbalancer.execute() : Executing R.E.S.T call to URL [%s] for response class [RestActionResponse] [%s]",url,urlVariables.toString() ));
	 		response = restTemplate.getForObject(url, RestActionResponse.class, urlVariables);
	 		if (response!=null)
		 	{
	 		 	return  response;
		 	}
		 	else
		 	{
		 		 return null;
		 	}	
		} catch (Exception e)
		{
	 		response = new RestActionResponse();
	 		response.setStatus(false);
	 		response.setResponseMessage(e.getMessage());
 	 		LOGGER.warn("loadbalancer.execute() : Error fetching rest url ["+url+"] Cause ["+e.getMessage()+"]");
	 		LOGGER.debug("loadbalancer.execute() : Error fetching rest url ["+url+"] ",e); 
		}
	 	 
		return response;
	 	
	}
 	
 

	public void setRestTemplate(RestOperations restTemplate)
	{
		this.restTemplate = restTemplate;
	}
	
	/*
	 * To check that node is alive or not, this class invokes ping rest service of engine.
	 * @param node 
	 * 
	 * */
	public boolean isAlive(Node node,Action pingAction)
	{
	 	String url = String.format(URLTemplate,node.getProtocol(),node.getHost(),node.getPort())+pingAction;
	 	RestActionResponse response = null;
	 	try 
	 	{
	 		response = restTemplate.getForObject(url, RestActionResponse.class);
	 		if (response!=null)
		 	{
		 		return response.isStatus();
		 	}
	 	}
	 	catch (Exception e) 
		{	 	
  			LOGGER.debug("loadbalancer.execute() : Error fetching rest url ["+url+"] ",e);
  			return false;
		}
	 	return false;
	}
	
	
	private String requestParamListTostring(List<RequestParameter> requestParameters)
	{
		StringBuilder stringBuilder =  threadLocalStringBuilder.get();
		stringBuilder.setLength(0);
		if (requestParameters!=null)
		{
			if (requestParameters.size()==1)
			{
				return requestParameters.get(0).toString();
			}
			 for (int i=0;i<requestParameters.size()-1;i++)
			 {
				 stringBuilder.append(requestParameters.get(i).toString());
				 stringBuilder.append("&");
			 }
			 stringBuilder.append(requestParameters.get(requestParameters.size()-1).toString());
			 return stringBuilder.toString();
		}
		
		return "";
	}
	
 }
